package com.zlq.cn;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.support.retrofit.Retrofit2ConverterFactory;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.zlq.cn.retrofit.RequestConfig;
import com.zlq.cn.retrofit.WanandroidResult;
import javazoom.jl.player.Player;
import one.util.streamex.EntryStream;
import one.util.streamex.StreamEx;
import org.apache.commons.lang3.StringUtils;
import retrofit2.Call;
import retrofit2.Retrofit;
import retrofit2.http.Body;
import retrofit2.http.POST;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.*;

public class HPV4Order {

    private static final int PID = 351661;

    private static final String VACCCODE = "5502";
    private static final String VACCNAME = "价HPV疫苗";
    private static final String VACCEFFECT = "四价人乳头瘤病毒疫苗（酿酒酵母）";

    private static final String DATE = "2022-08-09";

    private static final String REUS_TRUE_NAME = "蓝龙巧";

    private static final String OPEN_ID = "UNOEKvGH51ckDmMgfFjnM5rezKQrKM6gxchwn9YK2bA=";

    private static final Map<String, Integer> SORT_MAP;

    private static List<String> EXCLUDE_AREA_CODE = Arrays.asList("440310", "440307", "440308", "440312");

    public interface NewHealthApiService {

        /**
         * 社康疫苗列表
         */
        @POST("/vacc/service?function=vaccineorder&method=vaccorglist&visitcode=Pi0ynNDpmTJMf87i&token=cc8c78bdac1c7a2dd18aaf12cba57016")
        @RequestConfig(resultClz = WanandroidResult.class, retryCount = 3)
        Call<JSONObject> vaccorglist(@Body JSONObject body);

        /**
         * 社康排班
         */
        @POST("/vacc/service?function=vaccineorder&method=reservationstockDate&visitcode=Pi0ynNDpmTJMf87i&token=cc8c78bdac1c7a2dd18aaf12cba57016")
        @RequestConfig(resultClz = WanandroidResult.class, retryCount = 3)
        Call<JSONObject> reservationstockDate(@Body JSONObject body);

        /**
         * 接种人列表
         */
        @POST("/vacc/service?function=vaccineorder&method=adultlist&visitcode=Pi0ynNDpmTJMf87i&token=0edc0814150e229f53eb628f6c66cd86")
        @RequestConfig(resultClz = WanandroidResult.class, retryCount = 3)
        Call<JSONObject> adultlist(@Body JSONObject body);

        /**
         * 获取信息订阅列表
         */
        @POST("/dsmh/service?function=message&method=newstemplist&visitcode=Pi0ynNDpmTJMf87i&token=0edc0814150e229f53eb628f6c66cd86")
        @RequestConfig(resultClz = WanandroidResult.class, retryCount = 3)
        Call<JSONObject> newstemplist(@Body JSONObject body);

        /**
         * 订阅通知消息
         */
        @POST("/dsmh/service?function=message&method=subtemp&visitcode=Pi0ynNDpmTJMf87i&token=0edc0814150e229f53eb628f6c66cd86")
        @RequestConfig(resultClz = WanandroidResult.class, retryCount = 3)
        Call<JSONObject> subtemp(@Body JSONObject body);

        /**
         * 预约
         */
        @POST("/vacc/service?function=vaccineorder&method=vaccapply&visitcode=Pi0ynNDpmTJMf87i&token=0edc0814150e229f53eb628f6c66cd86")
        @RequestConfig(resultClz = WanandroidResult.class, retryCount = 3)
        Call<JSONObject> vaccapply(@Body JSONObject body);
    }

    private static final NewHealthApiService newHealthApiService;

    static {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://szhc.newhealth.com.cn/")
                .addConverterFactory(Retrofit2ConverterFactory.create())
                .build();
        newHealthApiService = retrofit.create(NewHealthApiService.class);

        List<String> SORT = new ArrayList<>();
        SORT.add("11:00");
        SORT.add("11:30");
        SORT.add("10:30");
        SORT.add("10:00");
        SORT.add("14:00");
        SORT.add("14:30");
        SORT.add("15:00");
        SORT.add("15:30");
        SORT.add("16:00");
        SORT.add("16:30");
        SORT.add("09:30");
        SORT.add("09:00");
        SORT.add("17:00");
        SORT.add("17:30");
        SORT.add("08:30");
        SORT.add("08:00");
        SORT_MAP = EntryStream.of(SORT).invert().toCustomMap(LinkedHashMap::new);
    }

    public static void main(String[] args) {
        // 登录
        // 获取人员列表
        // 刷疫苗社康列表
        vaccorglist();
//        reservationstockDate(null);
        // 进入社康排班列表
//        reservationstockDate("38BB4228-0313-461F-BB43-45592A05A1E8", "52");

//        JSONObject adultlist = adultlist();
//        System.out.println(adultlist);

//        List<JSONObject> newstemplist = newstemplist();
//        System.out.println(newstemplist);
    }

    /**
     * 刷可以预约的社康列表
     */
    private static void vaccorglist() {
        String param = "{\"areaCode\":\"4403\",\"pid\":351661,\"areaId\":\"4403\",\"numPerPage\":100,\"pageNum\":1,\"vaccCode\":\"5502\",\"reseCorpCode\":\"\",\"outpName\":\"\",\"vaccCrowd\":\"1\"}";
        int index = 1;
        while (true) {
            try {
                System.out.println(String.format("第%d次请求开始", index));
                JSONObject body = newHealthApiService.vaccorglist(JSON.parseObject(param)).execute().body();
                System.out.println(String.format("请求结果信息:%s", body.getString("message")));
                for (Object o : body.getJSONObject("data").getJSONArray("list")) {
                    JSONObject jsonObject = ((JSONObject) o);
                    if (Objects.equals("1", jsonObject.getString("flag")) && !startsWithAny(jsonObject.getString("depaCode"))) {
                        boolean success = reservationstockDate(jsonObject);
                        if (success) {
                            return;
                        }
                    }
                }
                System.out.println(String.format("第%d次请求没有可预约的社康", index));
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }
            try {
                long millis = RandomUtil.randomLong(1000, 3000);
                System.out.println(String.format("第%d次请求结束睡眠：%d", index, millis));
                Thread.sleep(millis);
                index++;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private static boolean startsWithAny(String depaCode) {
        for (String areaCode : EXCLUDE_AREA_CODE) {
            if (depaCode.startsWith(areaCode)) {
                System.out.println("命中排除的区：" + depaCode);
                return true;
            }
        }
        return false;
    }

    private static boolean reservationstockDate(JSONObject vaccorg) {
        String depaId = vaccorg.getString("depaId");
        String corpCode = vaccorg.getString("corpCode").split(",")[0];
//         String param = "{\"areaCode\":\"4403\",\"pid\":351661,\"areaId\":\"4403\",\"numPerPage\":100,\"pageNum\":1,\"vaccCode\":\"5502\",\"reseCorpCode\":\"\",\"outpName\":\"\",\"vaccCrowd\":\"1\"}";
//        String param = String.format("{\"depaId\":\"38BB4228-0313-461F-BB43-45592A05A1E8\",\"pid\":351661,\"vaccCrowd\":\"1\",\"corpCode\":\"40\"}");
        String param = String.format("{\"depaId\":\"%s\",\"pid\":351661,\"vaccCrowd\":\"1\",\"corpCode\":\"%s\"}", depaId, corpCode);
        try {
            JSONObject body = newHealthApiService.reservationstockDate(JSON.parseObject(param)).execute().body();
            List<JSONObject> sources = StreamEx.of(JSON.parseArray(body.getString("data"), JSONObject.class))
                    .flatMap(data -> StreamEx.of(
                            JSON.parseArray(data.getString("afternoon"), JSONObject.class),
                            JSON.parseArray(data.getString("morning"), JSONObject.class)
                    ).flatMap(Collection::stream))
                    .filter(dateJson -> DATE.equals(dateJson.getString("sdate")))
                    .flatMap(dataJson -> StreamEx.of(JSON.parseArray(dataJson.getString("source"), JSONObject.class)))
                    .filter(sourceJson -> sourceJson.getIntValue("avail") > 0)
                    .sortedBy(jsonObject -> SORT_MAP.getOrDefault(jsonObject.getString("timeBegin"), 99))
                    .toList();
            if (CollectionUtils.isNotEmpty(sources)) {
                new Thread(HPV4Order::play).start();
                JSONObject adultlist = adultlist();
                System.out.println("有可预约的时间段:" + sources);
                return vaccapply(adultlist, vaccorg, sources);
            } else {
                System.out.println("没有可预约的时间段");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

    private static JSONObject adultlist() {
        String param = "{\"pid\":351661,\"vaccCrowd\":\"1\"}";
        try {
            JSONObject body = newHealthApiService.adultlist(JSON.parseObject(param)).execute().body();
            List<JSONObject> jsonObjects = JSON.parseArray(body.getJSONObject("data").getString("registerUser"), JSONObject.class);
            return StreamEx.of(jsonObjects)
                    .findFirst(jsonObject -> REUS_TRUE_NAME.equals(jsonObject.getString("reusTrueName")))
                    .orElse(null);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    private static List<JSONObject> newstemplist() {
        String param = "{\"function\":\"vaccineorder1\"}";
        try {
            JSONObject body = newHealthApiService.newstemplist(JSON.parseObject(param)).execute().body();
            return JSON.parseArray(body.getString("data"), JSONObject.class);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    private static void subtemp(List<JSONObject> newstemplist) {
        if (CollectionUtils.isNotEmpty(newstemplist)) {
            JSONObject param = new JSONObject();
            param.put("openId", OPEN_ID);
            param.put("tempArray", newstemplist);
            try {
                JSONObject body = newHealthApiService.newstemplist(param).execute().body();
                System.out.println("消息订阅" + body.getString("message"));
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            System.out.println("可订阅消息列表为空不订阅");
        }
    }

    private static boolean vaccapply(JSONObject user, JSONObject vaccorg, List<JSONObject> sources) {
        if (user == null) {
            System.out.println("预约人没有找到");
            return false;
        }
        if (vaccorg == null) {
            System.out.println("社康没有找到");
            return false;
        }
        if (sources == null) {
            System.out.println("预约时间段没有找到");
            return false;
        }
        for (JSONObject source : sources) {
            JSONObject param = new JSONObject();
            param.put("pid", PID);
            param.putAll(user);
            param.put("depaId", vaccorg.get("outpName"));
            param.put("depaName", vaccorg.get("depaId"));
            param.put("areaName", vaccorg.get("areaName"));
            param.put("corpCode", vaccorg.getString("corpCode").split(",")[0]);
            param.put("reseCorpCode", vaccorg.getString("corpCode").split(",")[0]);
            param.put("vaccCrowd", "1");
            param.put("vaccCode", VACCCODE);
            param.put("vaccName", VACCNAME);
            param.put("vaccEffect", VACCEFFECT);
            param.put("ouatId", source.get("ouatId"));
            param.put("reseDate", DATE);
            param.put("ouatBeginTime", source.get("timeBegin"));
            param.put("ouatEndTime", source.get("timeEnd"));
            try {
                System.out.println("下单参数:" + param);
                JSONObject body = newHealthApiService.vaccapply(param).execute().body();
                if (1 == body.getIntValue("ret")) {
                    System.out.println("下单成功");
                    return true;
                } else {
                    System.out.println("下单失败" + body.getString("message"));
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return false;
    }

    private static void play() {
        try {
            File file = new File("D:\\development\\java\\project\\zlq\\src\\main\\resources\\static\\yiyi.mp3");
            Player player = new Player(new BufferedInputStream(new FileInputStream(file)));
            player.play();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
